﻿using System;

namespace NodeJS.http
{
    using NodeJS.net;
    public abstract class Server : net.Server
    {
        /// <summary>
        /// Emitted each time there is a request. Note that there may be multiple requests per connection (in the case of keep-alive connections). request is an instance of http.IncomingMessage and response is an instance of http.ServerResponse
        /// </summary>
        [EvalAtCompile(Value = "request")]
        public const NodeEvent<IncomingMessage, ServerResponse> REQUEST = null;

        /// <summary>
        /// When a new TCP stream is established. Usually users will not want to access this event. In particular, the socket will not emit readable events because of how the protocol parser attaches to the socket. The socket can also be accessed at request.connection.
        /// </summary>
        [EvalAtCompile(Value = "connection")]
        public const NodeEvent<Socket> CONNECTION = null;        

        /// <summary>
        /// Emitted each time a request with an http Expect: 100-continue is received. If this event isn't listened for, the server will automatically respond with a 100 Continue as appropriate.
        /// Handling this event involves calling response.writeContinue if the client should continue to send the request body, or generating an appropriate HTTP response (e.g., 400 Bad Request) if the client should not continue to send the request body.
        /// Note that when this event is emitted and handled, the request event will not be emitted.
        /// </summary>
        [EvalAtCompile(Value = "checkContinue")]
        public const NodeEvent<IncomingMessage, ServerResponse> CHECK_CONTINUE = null;

        /// <summary>
        /// Emitted each time a client requests a http CONNECT method. If this event isn't listened for, then clients requesting a CONNECT method will have their connections closed.
        /// After this event is emitted, the request's socket will not have a data event listener, meaning you will need to bind to it in order to handle data sent to the server on that socket.
        /// function (request, socket, head) { }
        /// <para> - request is the arguments for the http request, as it is in the request event.</para>
        /// <para> - socket is the network socket between the server and client.</para>
        /// <para> - head is an instance of Buffer, the first packet of the tunneling stream, this may be empty.</para>
        /// </summary>
        [EvalAtCompile(Value = "connect")]
        public new const NodeEvent<IncomingMessage, Socket, Buffer> CONNECT = null;

        /// <summary>
        /// Emitted each time a client requests a http upgrade. If this event isn't listened for, then clients requesting an upgrade will have their connections closed.
        /// After this event is emitted, the request's socket will not have a data event listener, meaning you will need to bind to it in order to handle data sent to the server on that socket.
        /// function (request, socket, head) { }
        /// <para> - request is the arguments for the http request, as it is in the request event.</para>
        /// <para> - socket is the network socket between the server and client.</para>
        /// <para> - head is an instance of Buffer, the first packet of the upgraded stream, this may be empty.</para>
        /// </summary>
        [EvalAtCompile(Value = "upgrade")]
        public const NodeEvent<IncomingMessage, Socket, Buffer> UPGRADE = null;

        /// <summary>
        /// If a client connection emits an 'error' event - it will forwarded here.
        /// function (exception, socket) { }
        /// <para> - socket is the net.Socket object that the error originated from.</para>
        /// </summary>
        [EvalAtCompile(Value = "clientError")]
        public const NodeEvent<Exception, Socket> CLIENT_ERROR = null;


        /// <summary>
        /// Begin accepting connections on the specified port and hostname.
        /// </summary>
        /// <param name="port"></param>
        /// <param name="host">If the hostname is omitted, the server will accept connections directed to any IPv4 address (INADDR_ANY).</param>
        /// <param name="backlog">Backlog is the maximum length of the queue of pending connections. The actual length will be determined by your OS through sysctl settings such as tcp_max_syn_backlog and somaxconn on linux. The default value of this parameter is 511 (not 512).</param>
        /// <param name="callback">The last parameter callback will be added as a listener for the 'listening' event.</param>
        public override void Listen(int port, string host = "127.0.0.1", int backlog = 511, Action callback = null)
        {
        }

        /// <summary>
        /// Start a UNIX socket server listening for connections on the given path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="callback">The last parameter callback will be added as a listener for the 'listening' event.</param>
        public override void Listen(string path, Action callback = null)
        {
        }

        /// <summary>
        /// Stops the server from accepting new connections.
        /// </summary>
        /// <param name="callback"></param>
        public override void Close(Action callback = null)
        {
        }

        /// <summary>
        /// Limits maximum incoming headers count, equal to 1000 by default. If set to 0 - no limit will be applied.
        /// </summary>
        public int MaxHeadersCount;

        /// <summary>
        /// The number of milliseconds of inactivity before a socket is presumed to have timed out.
        /// Note that the socket timeout logic is set up on connection, so changing this value only affects new connections to the server, not any existing connections.
        /// Set to 0 to disable any kind of automatic timeout behavior on incoming connections.
        /// </summary>
        public long Timeout;

        /// <summary>
        /// Sets the timeout value for sockets, and emits a 'timeout' event on the Server object, passing the socket as an argument, if a timeout occurs.
        /// If there is a 'timeout' event listener on the Server object, then it will be called with the timed-out socket as an argument.
        /// By default, the Server's timeout value is 2 minutes, and sockets are destroyed automatically if they time out. However, if you assign a callback to the Server's 'timeout' event, then you are responsible for handling socket timeouts.
        /// </summary>
        /// <param name="msecs"></param>
        /// <param name="callback"></param>
        public abstract void SetTimeout(long msecs, Action<Socket> callback);
    }
}
